/**
 * Dao for cart
 */
package vlms.dao;

import java.sql.*;
import java.util.*;

import vlms.bean.Account;
import vlms.bean.Cart;
import vlms.exception.CartException;


public class CartDAO {

	static HashMap<Integer,LinkedList<Cart>> listByPersonId;
	static HashMap<Integer,Cart> listByCartId;
	
	
	//Static Method Starts
	private static void staticPopulateVO(Cart dto, ResultSet rs) throws SQLException {
		dto.setCartid(rs.getInt("cartId"));
		dto.setMovieid(rs.getInt("movieId"));
		dto.setPersonid(rs.getInt("personId"));
	}
	
	private static void initializeList(Connection con)
	{		
		try {
			PreparedStatement stmt = null;
			ResultSet rs = null;				
			Cart dto;
			
			listByPersonId = new HashMap<Integer,LinkedList<Cart>>();
			listByCartId = new HashMap<Integer,Cart>();
			
			String SQL_STATEMENT = "Select * from Cart";
			stmt = con.prepareStatement(SQL_STATEMENT);
			rs = stmt.executeQuery();

			
			while (rs.next()) {
				dto = new Cart();
				staticPopulateVO(dto, rs);
					
				
				if(!listByPersonId.containsKey(dto.getPersonid())) {
					LinkedList<Cart> lCart = new LinkedList<Cart>();
					listByPersonId.put(dto.getPersonid(), lCart);
				}
				
				listByPersonId.get(dto.getPersonid()).add(dto);
				
				listByCartId.put(new Integer(dto.getCartid()), dto);
				
			}
			
		}			
		catch(SQLException se) {
		
			// The exception cannot be navigated back to the client. 
			// but as the initialization of list is failed. It will just
			// be printed as a error in the server console. This indicates
			// now the list is useless and every query is going to database 
			// instead of fetching from the list.
			System.out.println("Exception "+se+ " occured in the system." +
							   " Failed to initialize the list.");
			
		}
	}
	
	static 
	{
		Connection con = null;
		try {
			con = DriverManager.getConnection("jdbc:user_mysql:");
			initializeList(con);
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		try {
			con.close();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
		//Static Method Ends
	
	public Cart[] viewCart(int personId,Connection con) throws CartException{
		
		if(listByPersonId.get(personId) == null) {
			throw new CartException("Cart is Empty");
		}
		else {
			return (listByPersonId.get(personId).toArray(new Cart[listByPersonId.get(personId).size()]));
		}
		
		
	}
	
	public int delete(int cartId, Connection con) throws CartException, SQLException {
			PreparedStatement ps = null;
			int rowsUpdated = 0;
			Cart oListCart;
									
			ps = con.prepareStatement("delete from  CART where cartId = ?");
			ps.setInt(1, cartId);
			rowsUpdated = ps.executeUpdate();
			
			
			
			if(rowsUpdated == 0) {
				throw new CartException("No such Movie found in cart");
			}
			else {
			
				if((oListCart = listByCartId.get(cartId)) !=null) {
					listByPersonId.get(oListCart.getPersonid()).remove(oListCart);
					if(listByPersonId.get(oListCart.getPersonid()).isEmpty()) {
						listByPersonId.remove(oListCart.getPersonid());
					}
					listByCartId.remove(cartId);
				}			
			}
			
			return (rowsUpdated);		
	}

	//Not required
	public int update(int cartId, Cart cart, Connection con) throws CartException {
		PreparedStatement ps = null;
		try {
			ps = con.prepareStatement("update CART set PERSONID = ? , MOVIEID = ?  where cartId = ?");
			ps.setInt(1, cart.getPersonid());
			ps.setInt(2, cart.getMovieid());
			ps.setInt(3, cartId);

			return (ps.executeUpdate());
		} catch (SQLException sqle) {
			throw new CartException(sqle);
		} catch (Exception e) {
			throw new CartException(e);
		}
	}
	//
	
	
	
	public Cart insert(int movieId,int personId, Connection con) throws CartException, SQLException {

			PreparedStatement ps = null;
			int rowsUpdated = 0;
			
			Cart cart = new Cart();
			cart.setMovieid(movieId);
			cart.setPersonid(personId);
			
			System.out.println("MovieId: " + movieId + "  person id " + personId);
			
			if(listByPersonId.get(personId) != null) {
				System.out.println("Entered in 1st if");
				Iterator<Cart> it = listByPersonId.get(personId).iterator();
				while(it.hasNext()) {
					if(it.next().getMovieid() == movieId) {
						System.out.println("Entered in 2nd if");
						throw new CartException("Movie Already in Cart");
					}
				}
			}
			
			System.out.println("Entered out of 1st if");
			
			ps = con.prepareStatement("Select count(cartid) as countCartId from cart where personid = ? and movieid = ?");
			ps.setInt(1, cart.getPersonid());
			ps.setInt(2, cart.getMovieid());

			ResultSet rs = ps.executeQuery();
			rs.next();
			if(rs.getInt("countCartId") > 0) {
				
				System.out.println("Entered in 3rd if");
				throw new CartException("Movie Already in Cart");
			}
								
			ps = con.prepareStatement("insert into CART(PERSONID, MOVIEID) values (?, ?)");
			ps.setInt(1, cart.getPersonid());
			ps.setInt(2, cart.getMovieid());

			rowsUpdated = ps.executeUpdate();
			
			
			if(rowsUpdated == 0) {
				System.out.println("Entered in 4thst if");
				throw new CartException("Movie already in cart");
			}
			else {
				System.out.println("Entered in 5st if");
				Cart aCart[] = findExecutingUserSelect("SELECT cartId, personId, movieId from CART WHERE movieId = ? and personId = ?",
						new Object[]{cart.getMovieid(),cart.getPersonid()},con);
				
				if(listByPersonId.get(personId) == null) {
					System.out.println("Entered in 6th if");
					LinkedList<Cart> lCart = new LinkedList<Cart>();
					listByPersonId.put(cart.getPersonid(), lCart);
				}
				listByPersonId.get(cart.getPersonid()).add(aCart[0]);
				listByCartId.put(aCart[0].getCartid(), aCart[0]);
				System.out.println(listByPersonId.toString());
				cart = aCart[0];
			}
			
			return (cart);
		
	}

	public Cart findByPrimaryKey(int cartId, Connection con) throws CartException, SQLException {
		PreparedStatement stmt = null;
		ResultSet rs = null;
		
		Cart oCart = listByCartId.get(cartId);
		
		if(oCart == null) {		
		
			final String SQLSTATEMENT = "Select cartId, personId, movieId from cart where cartId = ?";
			stmt = con.prepareStatement(SQLSTATEMENT);
			stmt.setInt(1, cartId);
			rs = stmt.executeQuery();
			oCart = fetchSingleResult(rs);
			if(oCart != null) { 
				listByCartId.put(cartId, oCart);
				listByPersonId.get(oCart.getPersonid()).add(oCart);
			}
			else {
				throw new CartException("No such Movie in Cart");
			}
		}
		
		return oCart;
	}

	public Cart[] findByPersonId(int personId, Connection con) throws CartException, SQLException {
		
		Cart[] aCart = null;
		int i=0;
		int size = listByPersonId.get(personId).size();
		System.out.println("Size: " + size);
		if(size == 0) {
			throw new CartException("Cart is Empty");
		}
		
		aCart = listByPersonId.get(personId).toArray(new Cart[size]);
		
		return aCart;
	}

		

	public Cart[] findExecutingUserSelect(String selectStatement,
			Object[] sqlParams, Connection con) throws CartException, SQLException {
		PreparedStatement stmt = null;
		ResultSet rs = null;
		final String SQL_STATEMENT = selectStatement;
		
			stmt = con.prepareStatement(SQL_STATEMENT);
			for (int i = 0; i < sqlParams.length; i++) {
				stmt.setObject(i + 1, sqlParams[i]);
			}
			rs = stmt.executeQuery();
			return fetchMultiResults(rs);
		
	}

	public Cart[] findExecutingUserWhere(String whereClause,
			Object[] sqlParams, Connection con) throws CartException, SQLException {
		PreparedStatement stmt = null;
		ResultSet rs = null;
		String SQL_SELECT = "Select cartId, personId, movieId from cart";
		final String SQL_STATEMENT = SQL_SELECT + " where " + whereClause;
		
			stmt = con.prepareStatement(SQL_STATEMENT);
			for (int i = 0; i < sqlParams.length; i++) {
				stmt.setObject(i + 1, sqlParams[i]);
			}
			rs = stmt.executeQuery();
			return fetchMultiResults(rs);
		
	}

	protected Cart fetchSingleResult(ResultSet rs) throws SQLException {
		if (rs.next()) {
			Cart dto = new Cart();
			populateVO(dto, rs);
			return dto;
		} else {
			return null;
		}
	}

	protected void populateVO(Cart dto, ResultSet rs) throws SQLException {
		dto.setCartid(rs.getInt("cartId"));
		dto.setPersonid(rs.getInt("personId"));
		dto.setMovieid(rs.getInt("movieId"));
	}

	protected Cart[] fetchMultiResults(ResultSet rs) throws SQLException {
		Collection<Cart> resultList = new ArrayList<Cart>();
		while (rs.next()) {
			Cart dto = new Cart();
			populateVO(dto, rs);
			resultList.add(dto);
		}
		Cart ret[] = new Cart[resultList.size()];
		resultList.toArray(ret);
		return ret;
	}
}
